/*
 *  Created at 2011-01-09 14:13 GMT-03:00
 *  Author: Victor Williams Stafusa da Silva
 *  JSmartUnit
 */
package org.jsmartunit.core;

import org.jsmartunit.invocations.ClassInvocation;
import org.jsmartunit.model.TestRunner;

import org.junit.internal.AssumptionViolatedException;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.Filterable;
import org.junit.runner.manipulation.Sortable;
import org.junit.runner.manipulation.Sorter;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunNotifier;
import org.junit.runner.notification.StoppedByUserException;
import org.junit.runners.model.InitializationError;

/**
 * This is the main class of JSmartUnit framework. It is responsible for
 * marking a test class as a JSmartUnit test class.
 * <br>
 * Use it in your tests this way:
 * <pre>
 * package example;
 *
 * import org.junit.runner.RunWith;
 * import org.jsmartunit.core.JSmartUnit;
 *
 * &#64;RunWith(JSmartUnit.class)
 * public class MyTest {
 *     // ... Put your tests here.
 * }
 * </pre>
 *
 * @author Victor Williams Stafusa da Silva
 */
public class JSmartUnit extends Runner implements Sortable, Filterable {

    private final Class<?> testClass;
    private Description description;
    private Filter filter;
    private Sorter sorter;

    public JSmartUnit(Class<?> testClass) throws InitializationError {
        this.testClass = testClass;
        this.description = Description.createSuiteDescription(testClass);
    }

    @Override
    public Description getDescription() {
        return description;
    }

    @Override
    public void run(RunNotifier notifier) {

        try {
            TestRunner runner = new ClassInvocation("", notifier, testClass).createRunner();
            description = runner.getDescription();
            runner.filter(filter);
            description = runner.getDescription();
            runner.sort(sorter);
            description = runner.getDescription();
            runner.evaluate();
        } catch (AssumptionViolatedException e) {
            notifier.fireTestIgnored(description);
        } catch (StoppedByUserException e) {
            throw e;
        } catch (Throwable e) {
            notifier.fireTestFailure(new Failure(description, e));
        }
    }

    @Override
    public void sort(Sorter sorter) {
        this.sorter = sorter;
    }

    @Override
    public void filter(Filter filter) {
        this.filter = filter;
    }
}
